<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>待办事项列表</title>
</head>
<body>
  <div id="app">
    <todo-header></todo-header>
    <todo-input v-on:add="addTodoItem"></todo-input>
    <todo-list v-bind:list="todos"></todo-list>
  </div>

  <script src="./libs/vue.js"></script>
  <script>
    // 创建一个全局变量，用于表示 Event-Bus 中的对象
    const bus = new Vue()

    // TodoHeader 组件选项
    const headerOptions = {
      template: `
        <div class="todo-header">
          <h1>待办事项列表</h1>
          <h2>今日事今日毕</h2>
        </div>
      `
    }

    // TodoInput 组件选项
    const inputOptions = {
      template: `
        <div class="todo-input">
          <input
            placeholder="请输入新待办事项"
            v-model.trim="inputValue"
            ref="inputRef"
            @keydown.enter="handleAdd"
          />
          <button @click="handleAdd">添加</button>
        </div>
      `,
      data() {
        return {
          inputValue: ''
        }
      },
      methods: {
        // 处理点击添加
        handleAdd() {
          // 文本框自动获得焦点
          this.$refs.inputRef.focus()
          // 如果输入内容为空，则不添加
          if (this.inputValue.length === 0) {
            return
          }
          // 触发由父组件绑定的事件
          this.$emit('add', this.inputValue)
          // 清空文本框
          this.inputValue = ''
        }
      }
    }

    // TodoItem 选项对象
    const itemOptions = {
      template: `
        <li class="todo-item">
          <span>{{ todo.title }} - {{ todo.completed }}</span>
          <button @click="handleToggle">标记为{{ todo.completed ? '未' : '已' }}完成</button>
          <button @click="handleRemove">删除</button>
        </li>
      `,
      props: ['todo'],
      methods: {
        handleToggle() {
          // 修改状态，需要向祖先节点传递数据
          // 触发在全局 event-bus 中注册的 toggle 事件
          bus.$emit('toggle', this.todo.id)
        },
        handleRemove() {
          // 触发在全局 event-bus 中注册的 remove 事件
          bus.$emit('remove', this.todo.id)
        }
      }
    }

    // TodoList 选项
    const listOptions = {
      template: `
        <div class="todo-list">
          <div class="tabs">
            <button>所有</button>
            <button>已完成</button>
            <button>未完成</button>
          </div>

          <ul>
            <todo-item
              v-for="todo in list"
              :todo="todo"
            ></todo-item>
          </ul>
        </div>
      `,
      components: { // 局部注册子组件
        'todo-item': itemOptions
      },
      // props: ['list'], // 使用数组定义接收属性的名称
      props: { // 使用对象定义接收到属性的各项验证规则
        list: {
          type: Array,
          default: () => []
        }
      }
    }
    // <li
    //           is="todo-item"
    //           v-for="todo in list"
    //         ></li>

    // 全局注册组件
    Vue.component('todo-header', headerOptions)
    Vue.component('todo-input', inputOptions)
    Vue.component('todo-list', listOptions)

    // 全局待办事项 id 编号
    let index = 3

    // App 组件
    const App = new Vue({
      el: '#app',
      data: {
        // 定义数组来保存所有待办事项
        todos: [
          {
            id: 1,
            title: '复习 JavaScript',
            completed: true
          },
          {
            id: 2,
            title: '使用 vue 实现待办事项列表',
            completed: false
          }
        ]
      },
      methods: {
        /**
         * 添加新待办事项
         */
        addTodoItem(title) {
          this.todos.push({
            id: index++,
            title,
            completed: false
          })
        },
        /**
         * 切换待办事项状态
         */
        toggleTodoItem(id) {
          this.todos = this.todos.map(todo => {
            const copy = { ...todo }
            if (copy.id === id) {
              copy.completed = !copy.completed
            }
            return copy
          })
        },
        /**
         * 删除待办事项
         */
        removeTodoItem(id) {
          this.todos = this.todos.filter(todo => todo.id !== id)
        }
      },
      // 这是一个生命周期的钩子函数，是在 vue 实例创建后执行
      // 先暂时固定记住
      created() {
        // 调用全局 event-bus 对象，注册事件监听，准备接收数据
        bus.$on('toggle', this.toggleTodoItem)
        bus.$on('remove', this.removeTodoItem)
      }
    })
  </script>
</body>
</html>